package com.example.smartcity.ui.home

import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.smartcity.App.Companion.url
import com.example.smartcity.R
import com.example.smartcity.databinding.FragmentHomeBinding
import com.example.smartcity.logic.Repository.api
import com.example.smartcity.logic.Repository.coroutine
import com.example.smartcity.logic.model.BannerModel
import com.example.smartcity.logic.model.HotNewsModel
import com.example.smartcity.logic.util.Util.glide
import com.example.smartcity.logic.util.Util.show
import com.example.smartcity.ui.home.News.ShowNewsInfoActivity
import com.example.smartcity.ui.home.News.ShowNewsListActivity
import com.example.smartcity.ui.home.adapter.HomeHotRecyclerAdapter
import com.example.smartcity.ui.home.adapter.HomeMoreRecyclerAdapter
import com.example.smartcity.ui.home.fragment.ShowNewsFragment
import com.example.smartcity.ui.home.fragment.ShowNewsFragment.Companion.showNewsId
import com.example.smartcity.ui.home.model.HomeService
import com.google.android.material.tabs.TabLayoutMediator
import com.youth.banner.adapter.BannerImageAdapter
import com.youth.banner.holder.BannerImageHolder
import com.youth.banner.indicator.CircleIndicator
import kotlinx.coroutines.Dispatchers

/**
 * 主页
 */
class HomeFragment : Fragment() {
    private var _binding: FragmentHomeBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = FragmentHomeBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 启动协程
        runThreadService()

        // 新闻专栏
        classTabLayout()

        // 搜索框实现
        Seek()
    }


    /**
     * 该函数使用了Kotlin协程来启动后台线程，并在其中调用getBanner()函数来获取轮播图数据。
     */
    private fun runThreadService() = coroutine(Dispatchers.IO) {
        // 获取轮播图
        getBanner()
        // 获取推荐服务
        getService()
        // 获取热门主题
        getHot()
    }


    /**
     * TODO 轮播图
     *
     * 该函数是一个挂起函数，用于通过网络请求获取轮播图数据。使用了Retrofit库生成的接口api，
     * 并通过mapOf方法封装查询参数。如果服务器返回的数据正确，则将数据加入到arrayBanner中，并通过UI线程更新UI界面显示轮播图。
     */
    // 定义了一个存储轮播图数据的列表arrayBanner，类型为ArrayList<BannerModel.RowsDTO>。
    var arrayBanner = ArrayList<BannerModel.RowsDTO>()
    private suspend fun getBanner() {
        // 使用Retrofit库生成的接口api来获取轮播图数据。调用了getBanner方法，并通过mapOf方法封装查询参数。
        val result = api.getBanner(mapOf("pageNum" to 1, "pageSize" to 8, "type" to 2))

        //判断服务器返回的数据是否正确。如果返回码为200，则将数据加入到arrayBanner中，并通过UI线程更新UI界面显示轮播图；否则，在UI线程中弹出提示信息。
        if (result.code == 200) {
            // 清空原先数据
            arrayBanner.clear()
            arrayBanner.addAll(result.rows!!)
            activity?.runOnUiThread {

                // Banner适配器
                binding.homeBanner.apply { // 使用Kotlin中的扩展函数apply对binding.homeBanner进行设置。

                    //使用BannerImageAdapter适配器将轮播图数据加载到homeBanner中，并设置圆角、指示器等属性。
                    this.adapter = object : BannerImageAdapter<BannerModel.RowsDTO>(arrayBanner) {

                        //重写了BannerImageAdapter中的抽象方法，用于加载轮播图图片。在这里，使用Glide库加载图片，并根据服务器地址和图片名称拼接URL。
                        override fun onBindView(
                            p0: BannerImageHolder?,
                            p1: BannerModel.RowsDTO?,
                            p2: Int,
                            p3: Int
                        ) {
                            // 在app对象里面定义一个url，方便我们以后调用服务器地址
                            // const val url = "http://124.93.196.45:10001/"
                            glide(url + p1?.advImg, p0?.imageView!!)
                        }
                    }
                    // 添加生命周期观察者，当页面销毁时自动停止轮播图，并设置指示器样式。
                    this.addBannerLifecycleObserver(this@HomeFragment).indicator =
                        CircleIndicator(context)
                    // 设置轮播图的圆角为25像素。
                    this.setBannerRound(25f)

                    this.setOnBannerListener { any, i ->
                        // 为 banner 设置点击监听器
                        // 根据索引获取我们点击的照片对应的新闻 id
                        val newsId = when (i) {
                            0 -> 25
                            1 -> 26
                            else -> 27
                        }

                        // 启动 ShowNewsInfoActivity 并将该新闻 id 以 "id" 为 key 进行传递
                        startActivity(
                            Intent(context, ShowNewsInfoActivity::class.java)
                                .putExtra("id", newsId.toString())
                        )
                    }
                }
            }
        } else {
            activity?.runOnUiThread {
                "加载轮播图出错！".show()
            }
        }
    }


    /**
     * TODO 推荐服务
     */
    // 定义一个 ArrayList 变量 arrayService 用于保存获取到的数据
    private var arrayService = ArrayList<HomeService>()

    // 定义一个挂起函数 getService，用于调用接口获取数据并更新 RecyclerView 的适配器
    private suspend fun getService() {
        // 调用 api.getService() 方法获取服务数据
        val result = api.getService()

        // 清空之前的数据
        arrayService.clear()

        // 如果状态码为 200，说明获取成功，将数据添加到 arrayService 列表中，并更新 RecyclerView 的适配器
        if (result.code == 200) {
            // 将获取到的数据添加到 arrayService 中
            for (i in result.rows!!) {
                arrayService.add(HomeService(true, i.imgUrl!!, i.serviceName!!))
            }

            // 在 UI 线程中设置 RecyclerView 的属性和适配器
            activity?.runOnUiThread {
                // 设置 isNestedScrollingEnabled 属性为 false，确保滑动性能良好
                binding.homeMoreRecyclerView.isNestedScrollingEnabled = false

                // 设置 layoutManager 为 GridLayoutManager，以网格布局方式显示子项视图
                binding.homeMoreRecyclerView.layoutManager = GridLayoutManager(context, 5)

                // 设置 adapter 为 HomeMoreRecyclerAdapter，并传入数据列表 arrayService 和子项布局文件 re_home_item
                binding.homeMoreRecyclerView.adapter =
                    HomeMoreRecyclerAdapter(this, arrayService, R.layout.re_home_item, 10)

                // 更新 RecyclerView 的适配器
                binding.homeMoreRecyclerView.adapter?.notifyItemChanged(arrayService.size)
            }
        } else {
            // 否则提示加载服务失败
            // 在 UI 线程中弹出提示框
            activity?.runOnUiThread {
                "加载服务失败！".show()
            }
        }
    }


    /**
     * TODO 热门主题
     */
    // 声明一个 ArrayList，用于存储热门新闻数据模型对象
    private var arrayHot = ArrayList<HotNewsModel.RowsDTO>()

    // 定义一个挂起函数，用于获取热门新闻数据
    private suspend fun getHot() {
        // 每次调用挂起函数先把arrayHot集合清空
        arrayHot.clear()

        // 调用 API 接口获取热门新闻数据
        val result = api.getHotNews("Y")

        // 如果返回码为 200，则表示请求成功，将获取到的数据添加到 arrayHot 中
        if (result.code == 200) {
            arrayHot.addAll(result.rows!!)

            // 在 UI 线程中更新 RecyclerView 的布局、适配器、滚动等设置
            activity?.runOnUiThread {
                binding.homeHotRecyclerView.apply {
                    this.layoutManager = LinearLayoutManager(context).apply {
                        this.orientation = LinearLayoutManager.HORIZONTAL
                    }
                    this.adapter = HomeHotRecyclerAdapter(arrayHot, R.layout.re_home_item_hot)
                    this.isNestedScrollingEnabled = false
                    this.adapter?.notifyItemChanged(arrayHot.size)
                }
            }
        } else {
            // 如果返回码不为 200，则表示请求失败，弹出提示信息
            activity?.runOnUiThread {
                "加载热门主题失败！".show()
            }
        }
    }


    /**
     * TabLayout / ViewPager2
     */
    // 定义一个方法，用于创建 TabLayout 和 ViewPager2 并进行关联
    private fun classTabLayout() {

        // 设置 ViewPager2 的适配器
        binding.homeVp2.adapter = object : FragmentStateAdapter(this) {

            override fun getItemCount(): Int = 6

            // 根据不同的位置返回对应的 Fragment
            override fun createFragment(position: Int): Fragment = when (position) {
                0 -> ShowNewsFragment()
                1 -> ShowNewsFragment()
                2 -> ShowNewsFragment()
                3 -> ShowNewsFragment()
                4 -> ShowNewsFragment()
                else -> ShowNewsFragment()
            }

            /**
             * 根据不同的数值更新不同的新闻列表
             * 数值怎么获取呢？
             * 在api文档中有提供
             */
            override fun getItemId(position: Int): Long {
                // 根据不同的位置更新不同的新闻分类 ID
                showNewsId = when (position) {
                    0 -> 9
                    1 -> 17
                    2 -> 19
                    3 -> 20
                    4 -> 21
                    else -> 22
                }
                return super.getItemId(position)
            }
        }

        // 将 TabLayout 和 ViewPager2 进行关联
        TabLayoutMediator(binding.homeTab, binding.homeVp2) { tab, position ->
            // 根据不同的位置设置对应的标签文本
            when (position) {
                0 -> tab.text = "今日要闻"
                1 -> tab.text = "专题聚焦"
                2 -> tab.text = "政策解读"
                3 -> tab.text = "经济发展"
                4 -> tab.text = "文化旅游"
                else -> tab.text = "科技创新"
            }
        }.attach()
    }


    /**
     * 实现主页搜索框
     */
    // 定义 Seek 方法
    private fun Seek() {
        // 设置 homeSeek 的编辑完成监听器，当用户点击“搜索”按钮时触发
        binding.homeSeek.setOnEditorActionListener { textView, i, keyEvent ->
            if (i == EditorInfo.IME_ACTION_SEARCH) {
                // 获取用户输入的内容
                val content = binding.homeSeek.text.toString()
                // 启动 ShowNewsListActivity 并将用户输入的内容以 intent 方式传递给该 Activity
                startActivity(
                    Intent(context, ShowNewsListActivity::class.java)
                        .putExtra("content", content)
                )
            }
            false   // 返回 false 表示事件未被处理完毕，会让 EditText 继续监听事件
        }
    }


    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}